#ifndef _MODEL_H_
#define _MODEL_H_

#include <vector>
#include <cstring>
#include <fstream>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <iostream>

#include <QObject>

#include "renderer.h"

using namespace std;

class Model : public QObject
{
   Q_OBJECT
   
   public:
      Model( QObject *parent = 0 );
      ~Model();
      Model( const char* filename, QObject* parent = 0 );
      
      /**
      * Detects model format and loads model from file.
      * @param filename Filename to load
      * @return 0 on success, negative otherwise
      */
      int load( const char *filename );
      
      /**
      * Loads Waveform (.obj) model from file.
      * @param filename Filename to load
      * @return 0 on success, -1 on wrong parameter, -2 on file management error
      */
      int loadObj( const char *filename );
      
      /**
      * Moves model to absolute position.
      * @param x x coordinate
      * @param y y coordinate
      * @param z z coordinate
      */
      void moveTo( float x, float y, float z );
      
      /**
      * Moves model relatively to previous position.
      * @param x x axis shift
      * @param y y axis shift
      * @param z z axis shift
      */
      void move( float x, float y, float z );
      
      /**
      * Rotates model around specified axis by specified angle.
      * @param x x axis coordinate
      * @param y y axis coordinate
      * @param z z axis coordinate
      */
      void rotate( float x, float y, float z, float angle );
      
      /**
      * Scales model by factor.
      * @param factor
      */
      void scale( float factor );
      
      /**
      * Prints model data for debuging purposes.
      */
      void print();
      
      /**
      * Renders model on specified renderer.
      * @param renderer
      */
      void render(Renderer* renderer);
      
      /**
      * Checks if hidden surface removal is enabled.
      * @return true if enabled, false otherwise
      */
      bool hiddenSurfaceRemovalEnabled();
      
      /**
      * Checks if polygon with specified vertices is turned towards us.
      * @return true if visible, false otherwise
      */
      bool checkVisibility(RendererVertex v1, RendererVertex v2, RendererVertex v3);

   public slots:
      /**
      * Enables or disables hidden surface removal.
      * @param enable set to true to enable, false to disable
      */
      void setHiddenSurfaceRemovalEnabled( bool enable = true );
        
        
    private:
        struct poly
        {
            vector<int> poly;
            vector<int> tex;
            vector<int> normal;
        };
        struct tex
        {
            int x;
            int y;
        };
        struct normal
        {
            int x;
            int y;
            int z;
        };
        vector<Vertex3D> m_vx;
        vector<poly> m_poly;
        RendererVertex* m_transformed;
        bool m_hiddenSurfaceRemovalEnabled;

        vector<tex> m_tex;
        vector<normal> m_normal;

	float m_posX;
	float m_posY;
	float m_posZ;
	
	float m_axisX;
	float m_axisY;
	float m_axisZ;
	float m_angle;
	
	float m_scaleFactor;
};

#endif
